package com.mashiro.system.service.impl;

import com.mashiro.common.core.domain.entity.SysUser;
import com.mashiro.common.utils.DateUtils;
import com.mashiro.common.utils.SecurityUtils;
import com.mashiro.system.domain.*;
import com.mashiro.system.domain.data.ProjectData;
import com.mashiro.system.domain.data.ProjectFundData;
import com.mashiro.system.domain.data.ProjectInitAndFinishData;
import com.mashiro.system.domain.data.ProjectTypeData;
import com.mashiro.system.domain.status.MoeAcceptanceStatus;
import com.mashiro.system.domain.status.MoeProjectStatus;
import com.mashiro.system.domain.types.MoeMessageType;
import com.mashiro.system.mapper.*;
import com.mashiro.system.service.IMoeProjectService;
import com.mashiro.system.service.IMoeTaskService;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 项目Service业务层处理
 *
 * @author mashiro
 * @date 2023-04-15
 */
@Service
public class MoeProjectServiceImpl implements IMoeProjectService {
    @Resource
    private MoeProjectMapper moeProjectMapper;
    @Resource
    private MoeTaskMapper moeTaskMapper;
    @Resource
    private MoeAcceptanceMapper moeAcceptanceMapper;
    @Resource
    private MoeFundMapper moeFundMapper;
    @Resource
    private MoeContractualMapper moeContractualMapper;
    @Resource
    private MoeMessageMapper moeMessageMapper;

    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private IMoeTaskService iMoeTaskService;

    @Value("${mashiro.project.warnDay:3}")
    private int warnDay;

    /**
     * 查询项目
     *
     * @param id 项目主键
     * @return 项目
     */
    @Override
    public MoeProject selectMoeProjectById(Long id) {
        return moeProjectMapper.selectMoeProjectById(id);
    }

    /**
     * 查询项目列表
     *
     * @param moeProject 项目
     * @return 项目
     */
    @Override
    public List<MoeProject> selectMoeProjectList(MoeProject moeProject) {
        return moeProjectMapper.selectMoeProjectList(moeProject);
    }

    /**
     * 新增项目
     *
     * @param moeProject 项目
     * @return 结果
     */
    @Override
    @Transactional
    public int insertMoeProject(MoeProject moeProject) {
        MoeFund moeFund = new MoeFund();
        Date nowDate = DateUtils.getNowDate();
        moeProject.setCreateTime(nowDate);
        moeProjectMapper.insertMoeProject(moeProject);
        moeFund.setProjectId(moeProject.getId());
        moeFund.setTaskId(0L);
        moeFund.setName(moeProject.getName());
        moeFund.setCreateTime(nowDate);
        int i = moeFundMapper.insertMoeFund(moeFund);
        return i;
    }

    /**
     * 修改项目
     *
     * @param moeProject 项目
     * @return 结果
     */
    @Override
    @Transactional
    public int updateMoeProject(MoeProject moeProject) {
        Date nowDate = DateUtils.getNowDate();
        if(moeProject.getStatus().equals(MoeProjectStatus.ONGOING.getValue())){
            MoeAcceptance moeAcceptance = moeAcceptanceMapper.selectMoeAcceptanceByProjectId(moeProject.getId());
            if (!Objects.isNull(moeAcceptance)){
                moeAcceptance.setStatus(MoeAcceptanceStatus.PENDING.getValue());
                moeAcceptance.setUpdateTime(nowDate);
                moeAcceptanceMapper.updateMoeAcceptance(moeAcceptance);
            }
        }
        moeProject.setUpdateTime(nowDate);
        return moeProjectMapper.updateMoeProject(moeProject);
    }

    /**
     * 批量删除项目
     *
     * @param ids 需要删除的项目主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteMoeProjectByIds(Long[] ids) {
        int i = 0;
        for (Long id : ids) {
            i += this.deleteMoeProjectById(id);
        }
        return i;
    }

    /**
     * 删除项目信息
     *
     * @param id 项目主键
     * @return 结果
     * @deprecated 项目删除：联表删除任务、资金、合同、验收
     */
    @Override
    @Transactional
    public int deleteMoeProjectById(Long id) {
        MoeTask moeTask = new MoeTask();
        MoeFund moeFund = new MoeFund();
        MoeAcceptance moeAcceptance = new MoeAcceptance();
        MoeContractual moeContractual = new MoeContractual();
        moeTask.setProjectId(id);
        moeFund.setProjectId(id);
        moeAcceptance.setProjectId(id);
        moeContractual.setProjectId(id);
        // 删除项目下的所有任务（包括 删除与任务管理的资金）
        List<MoeTask> moeTaskList = moeTaskMapper.selectMoeTaskList(moeTask);
        Long[] moeTaskIds = moeTaskList.stream().map(MoeTask::getId).toArray(Long[]::new);
        if (moeTaskIds.length > 0) {
            iMoeTaskService.deleteMoeTaskByIds(moeTaskIds);
        }
        // 删除项目下的所有资金
        List<MoeFund> moeFundList = moeFundMapper.selectMoeFundList(moeFund);
        Long[] moeFundIds = moeFundList.stream().map(MoeFund::getId).toArray(Long[]::new);
        if (moeFundIds.length > 0) {
            moeFundMapper.deleteMoeFundByIds(moeFundIds);
        }
        // 删除项目下的所有验收信息
        List<MoeAcceptance> MoeAcceptanceList = moeAcceptanceMapper.selectMoeAcceptanceList(moeAcceptance);
        Long[] MoeAcceptanceIds = MoeAcceptanceList.stream().map(MoeAcceptance::getId).toArray(Long[]::new);
        if (MoeAcceptanceIds.length > 0) {
            moeAcceptanceMapper.deleteMoeAcceptanceByIds(MoeAcceptanceIds);
        }
        // 删除项目下的所有合同信息
        List<MoeContractual> moeContractualList = moeContractualMapper.selectMoeContractualList(moeContractual);
        Long[] moeContractualIds = moeContractualList.stream().map(MoeContractual::getId).toArray(Long[]::new);
        if (moeContractualIds.length > 0) {
            moeContractualMapper.deleteMoeContractualByIds(moeContractualIds);
        }
        return moeProjectMapper.deleteMoeProjectById(id);
    }

    /**
     * 获取已分配占比
     *
     * @param id 项目主键
     * @return 结果
     */
    @Override
    public Integer getAllocatedProportion(Long id) {
        return moeProjectMapper.getAllocatedProportion(id);
    }

    /**
     * 获取项目当前进度情况
     *
     * @param id 项目主键
     * @return 结果
     */
    @Override
    public Integer getProjectScheduleDetails(Long id) {
        return moeProjectMapper.getProjectScheduleDetails(id);
    }

    /**
     * 结束项目
     *
     * @param id 项目主键
     * @return 结果
     */
    @Override
    @Transactional
    public int endProject(Long id) throws Exception {
        int scheduleDetails = 0;
        Integer projectScheduleDetails = moeProjectMapper.getProjectScheduleDetails(id);
        if (!Objects.isNull(projectScheduleDetails)) {
            scheduleDetails = projectScheduleDetails;
        }
        MoeProject moeProject = moeProjectMapper.selectMoeProjectById(id);
        if (scheduleDetails >= 0 && scheduleDetails < 10000) {
            moeProject.setStatus(MoeProjectStatus.FINISHED.getValue());// 已结束
        } else if (scheduleDetails == 10000) {
            MoeAcceptance moeAcceptance = new MoeAcceptance();
            MoeMessage message = new MoeMessage();
            if (MoeProjectStatus.REJECTED.getValue().equals(moeProject.getStatus())) {// 已提交未通过 状态
                moeAcceptance.setProjectId(id);
                MoeAcceptance acceptance = moeAcceptanceMapper.selectMoeAcceptanceByProjectId(moeAcceptance.getProjectId());
                acceptance.setStatus(MoeAcceptanceStatus.PENDING.getValue());
                moeAcceptanceMapper.updateMoeAcceptance(acceptance);// 修改验收表状态未 `未验收`
            } else {// 进行中 状态
                MoeAcceptance moeAcceptanceByProjectId = moeAcceptanceMapper.selectMoeAcceptanceByProjectId(id);
                if (Objects.isNull(moeAcceptanceByProjectId)){
                    try {
                        // 第一次验收，需要新建验收条目
                        moeAcceptance.setProjectId(id);
                        moeAcceptance.setStatus(MoeAcceptanceStatus.PENDING.getValue());
                        moeAcceptanceMapper.insertMoeAcceptance(moeAcceptance);
                    } catch (Exception e) {
                        if (e.getCause() instanceof SQLIntegrityConstraintViolationException) {
                            return 0;
                        }
                }
                }
            }
            moeProject.setStatus(MoeProjectStatus.SUBMITTED.getValue()); // 项目状态更正为 已提交未审批
            // 消息构造
            Long userId = SecurityUtils.getUserId();// 发送者
            String title = moeProject.getName() + "的项目验收单";// 标题
            String content = String.valueOf(moeAcceptance.getId());// 内容（验收条目ID）
            message.setSenderId(userId);
            message.setTitle(title);
            message.setType(MoeMessageType.APPROVAL.getValue());// 审批通知
            message.setContent(content);
            List<SysUser> projectAdminList = sysUserMapper.selectUserListByRole(10L);// 项目管理员列表
            projectAdminList.forEach((projectAdmin) -> {
                message.setReceiverId(projectAdmin.getUserId());
                moeMessageMapper.insertMoeMessage(message);
            });
        }
        return moeProjectMapper.updateMoeProject(moeProject);
    }

    /**
     * 获取项目的顶级任务列表
     *
     * @param id 项目主键
     * @return 结果
     */
    @Override
    public List<MoeTask> getTopTaskList(Long id) {
        MoeTask moeTask = new MoeTask();
        moeTask.setProjectId(id);
        moeTask.setTaskParentId(0L);
        return moeTaskMapper.selectMoeTaskList(moeTask);
    }

    /**
     * 获取处在预警期的项目
     *
     * @return 结果
     */
    @Override
    public List<MoeProject> getWarnProjectListByManagerId(Long id) {
        return moeProjectMapper.selectWarnProjectListByManagerId(id, warnDay);
    }

    /**
     * 查询项目ID列表通过项目经理ID
     *
     * @param
     * @return 项目集合
     */
    @Override
    public Long[] getMoeProjectIdsByManagerId(@Param("managerId") Long id) {
        return moeProjectMapper.selectMoeProjectIdsByManagerId(id);
    }

    @Override
    public List<ProjectTypeData> getMoeProjectTypeData() {
        return moeProjectMapper.selectMoeProjectTypeData(MoeProjectStatus.APPROVED.getValue());
    }

    @Override
    public List<ProjectData> getMoeProjectData() {
        return moeProjectMapper.selectMoeProjectData(MoeProjectStatus.APPROVED.getValue());
    }

    @Override
    public List<ProjectFundData> getProjectFundData() {
        return moeProjectMapper.selectProjectFundData();
    }

    @Override
    public List<ProjectInitAndFinishData> getProjectInitAndFinishData() {
        return moeProjectMapper.selectProjectInitAndFinishData();
    }

}
